package cloud.xlh.my_system.middle_aware.elasticsearch.utils;

import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class ElasticsearchUtil<T> {
    @Autowired
    private RestHighLevelClient client;

    // 索引的创建 request
    void createIndex(String indexName) throws IOException {
        // 1、创建索引请求
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        // 2、客户端执行请求 indexResponse, 请求后获得相应
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
    // 获取索引，只能判断其是否存在
    boolean isExistIndex(String indexName) throws IOException {
        GetIndexRequest request = new GetIndexRequest(indexName);
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
        return exists;
    }

    // 获取索引，不存在则创建
    void CreateIndexIfNotExit(String indexName) throws IOException {
        boolean isExist = isExistIndex(indexName);
        if (!isExist) {
            createIndex(indexName);
        }
    }
    // 删除索引
    void deleteIndex(String indexName) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());
    }

    //创建文档
    public void addDocument(String indexName , String mysqlId , T t ) throws IOException {
        isExistIndex(indexName);
        // 创建请求
        IndexRequest request = new IndexRequest(indexName);
        // 规则 put /kuang_index/_doc/1
        request.id(mysqlId);
        request.timeout(TimeValue.timeValueDays(1));
        //    request.timeout("1");
        // 将我们的数据放入请求 json
        request.source(JSON.toJSONString(t), XContentType.JSON);
        // 客户端发送请求，获取响应结果
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
        System.out.println(indexResponse.status());
    }
    // 获取文档，判断是否存在 get /index/doc/1
    boolean isExists(String indexName , String docId) throws IOException {
        GetRequest request = new GetRequest(indexName, docId);
        // 不获取返回的 _source 的上下文了
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
        return exists;
    }
    // 获取文档信息
    T getDocument(String indexName , String docId) throws IOException {
        GetRequest request = new GetRequest(indexName, docId);
        GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSourceAsString()); // 打印文档的内容
        System.out.println(getResponse);  // 返回的全部内容和命令是一样的
        return (T)getResponse.getSourceAsString();
    }
    // 更新文档的信息
    void updateDocument(String indexName , String docId , T t) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(indexName, docId);
        updateRequest.timeout("1s");
        updateRequest.doc(JSON.toJSONString(t), XContentType.JSON);
        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status());
    }
    // 删除文档记录
    public void deleteRequest(String indexName , String docId) throws IOException {
        DeleteRequest request = new DeleteRequest(indexName, docId);
        request.timeout("1s");
        DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.status());
    }
    // 批量插入
    void bulkRequest(String indexName , ArrayList<T> list) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        // 批处理请求
        for (int i = 0; i < list.size(); i++) {
            // 批量更新和批量删除，就在这里修改对应的请求就可以了
            bulkRequest.add(
                    new IndexRequest(indexName)
                            .id("" + (i + 1))
                            .source(JSON.toJSONString(list.get(i)), XContentType.JSON));
        }
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.hasFailures());  // 是否失败,返回false代表成功
    }
    // 查询
// SearchRequest 搜索请求
// SearchSourceBuilder 条件构造
// HighLightBuilder 构建高亮
// TermQueryBuilder  精确查询
// MatchAllQueryBuilder
// xxx QueryBuilder 对应我们刚才看到的命令！
    void search(String indexName , String name , QueryBuilders queryBuilders) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 构建搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询条件，我们可以使用 QueryBuilders 工具来实现
        // QueryBuilders.termQuery  精确
        //QueryBuilders.matchAllQuery 匹配所有
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", name);
        //    MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
        System.out.println("===========================");
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            System.out.println(documentFields.getSourceAsMap());
        }
    }

    public List<Map<String, Object>> QueryByCondition(String indexName , BoolQueryBuilder boolQueryBuilder , Integer page, Integer limit) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 构建搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询条件，我们可以使用 QueryBuilders 工具来实现
        // QueryBuilders.termQuery  精确
        //QueryBuilders.matchAllQuery 匹配所有
        //    MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        sourceBuilder.query(boolQueryBuilder);
        //分页
        sourceBuilder.from(page);
        sourceBuilder.size(limit);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
        System.out.println("===========================");
        List<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            list.add(documentFields.getSourceAsMap());
        }
        System.out.println(list);
        return list;
    }
}
